# Copyright (c) 2019 Presto Labs Pte. Ltd.
# Author: xguo

import json

from coin.base.book.types import TradeSide, create_market_trade_event
from coin.exchange.base.ws.handler import WebsocketHandler
from coin.exchange.coinone_v2.book_builder import BookBuilder
from coin.exchange.coinone_v2.kr_rest.native_private_client import is_success_response_msg


class RestHandlerAsOfWebsocket(WebsocketHandler):
  pass


class CoinoneRestHandler(RestHandlerAsOfWebsocket):
  def __init__(self, *, feed_checker_config=None):
    super().__init__(feed_checker_config=feed_checker_config)
    self._last_trade_ts = None

  # noinspection PyUnusedLocal
  def on_book(self, record, queue_data, topic_data):
    data = record.data
    if not isinstance(data, dict):
      data = json.loads(data.tobytes())

    if not is_success_response_msg(data):
      self._logger.error('Invalid msg received! %s', data)
      return

    native_symbol = data['currency']
    if not self.is_subscribed('book', native_symbol):
      return

    book = self._books.setdefault(native_symbol, BookBuilder(native_symbol))
    assert 'bids' in data
    assert 'asks' in data
    bids = data['bids']
    asks = data['asks']
    book.snapshot(bids, asks)
    book.update_timestamp(record.timestamp)
    self.ready = True
    self.publish_event('book', book.symbol, book)

  # noinspection PyUnusedLocal
  def on_trade(self, record, queue_data, topic_data):
    data = record.data
    if not isinstance(data, dict):
      data = json.loads(data.tobytes())

    if not is_success_response_msg(data):
      self._logger.error('Invalid msg received! %s', data)
      return

    native_symbol = data['currency']
    if not self.is_subscribed('trade', native_symbol):
      return

    filled_orders = data['completeOrders']
    if self._last_trade_ts is None:
      self._last_trade_ts = max(float(order_info['timestamp']) for order_info in filled_orders)
      return

    for item in filled_orders:
      trade_timestamp = float(item['timestamp'])
      ts_list = []
      if self._last_trade_ts < trade_timestamp:
        ts_list.append(trade_timestamp)
        price = float(item['price'])
        qty = float(item['qty'])
        side = TradeSide.TRADE_SELL_SIDE if int(item['is_ask']) == 1 else TradeSide.TRADE_BUY_SIDE
        trade_event = create_market_trade_event(record.timestamp, native_symbol, price, qty, side)
        self.publish_event('trade', native_symbol, trade_event)
        self._last_trade_ts = max(ts_list)
